<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta http-equiv=Content-Type content="text/html; charset=utf-8">
    <title>Adventures in ABAC - Part 2</title>
    <style>
     <!--
      /* Font Definitions */
      @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0;}
      @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4;}
      @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4;}
      @font-face {font-family:"Calibri Light"; panose-1:2 15 3 2 2 2 4 3 2 4;}

      /* Style Definitions */
      p.MsoNormal, li.MsoNormal, div.MsoNormal
             {margin:0in; font-size:12.0pt; font-family:"Calibri",sans-serif;}
     h1
             {mso-style-link:"Heading 1 Char"; margin-top:12.0pt; margin-right:0in; margin-bottom:0in; margin-left:0in; page-break-after:avoid; font-size:16.0pt; font-family:"Calibri Light",sans-serif; color:#2F5496; font-weight:normal;}

      p.MsoFootnoteText, li.MsoFootnoteText, div.MsoFootnoteText
             {mso-style-link:"Footnote Text Char"; margin:0in; font-size:10.0pt; font-family:"Calibri",sans-serif;}

      p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
             {margin-top:0in; margin-right:0in; margin-bottom:0in; margin-left:.5in; font-size:12.0pt; font-family:"Calibri",sans-serif;}
      p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst
             {margin-top:0in; margin-right:0in; margin-bottom:0in; margin-left:.5in; font-size:12.0pt; font-family:"Calibri",sans-serif;}
      p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle
             {margin-top:0in; margin-right:0in; margin-bottom:0in; margin-left:.5in; font-size:12.0pt; font-family:"Calibri",sans-serif;}
      p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast
             {margin-top:0in; margin-right:0in; margin-bottom:0in; margin-left:.5in; font-size:12.0pt; font-family:"Calibri",sans-serif;}
      span.Heading1Char
             {mso-style-name:"Heading 1 Char"; mso-style-link:"Heading 1"; font-family:"Calibri Light",sans-serif; color:#2F5496;}
      span.FootnoteTextChar
             {mso-style-name:"Footnote Text Char"; mso-style-link:"Footnote Text";}
      .MsoChpDefault
             {font-family:"Calibri",sans-serif;}

      /* Page Definitions */
      @page WordSection1
             {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in;}
      div.WordSection1
             {page:WordSection1;}


      /* List Definitions */
      ol
             {margin-bottom:0in;}
      ul
             {margin-bottom:0in;}
     -->
    </style>
  </head>

  <body lang=EN-US style='width:800px;word-wrap:break-word;align:center;margin:auto;border:ridge' >
    <div style="margin-left:10pt;margin-right:10pt">
      <h1 style="text-align:center">Adventures in attribute-based access control (ABAC) - Part 2</h1>
      <p class=MsoNormal style='font:5.0pt "Times New Roman"'>&nbsp;</p>
      <div style="text-align:center">
        <p class=MsoNormal>Barbara Eckman, Ph.D., Distinguished Architect, Comcast</p>
        <p class=MsoNormal>Oct 15, 2023</p>
      </div>
      <p class=MsoNormal>&nbsp;</p>

      <div class=WordSection>
        <h1>Introduction</h1>

        <p class=MsoNormal>
          Previously in <a href="./adventures_in_abac_1.html">Part 1</a> of this series we examined an increasingly
          complex series of use cases involving role membership and row filtering. While built-in Apache Ranger™
          TBAC, RBAC, and row-filter based access policies are powerful, they may not be sufficient for complex access
          control constraints. As the numbers of row filters that must be simultaneously enforced rises, the number of
          roles and row filter conditions increases combinatorially and rapidly becomes difficult to manage.
        </p>

        <p class=MsoNormal>&nbsp;</p>

        <p class=MsoNormal>
          This post introduces the principles of Attribute-based Access Control (ABAC) and shows how they enable us to
          avoid this potentially mushrooming complexity.  Let’s recall the final use case from part 1.
        </p>

        <p class=MsoNormal>&nbsp;</p>

        <h1>Recap: GlobalSalesPartners table row filters</h1>
        <p class=MsoNormal>
          The GlobalSalesPartners table includes info on which business partner (“ABC” or “XYZ”) produced the data, as
          well as the salesRegion where the sale occurred.
        </p>
        <p class=MsoNormal align=center style='text-align:center'>
            <img width=780 height=180 id="Picture 6" src="adventures_in_abac_2.files/table_globalsalespartners.jpg" alt="Table USSales">
        </p>
        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal>Recall our favorite users:</p>

        <table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0 style='margin-left:30.35pt;border-collapse:collapse;border:none'>
          <tr>
            <td width=90 valign=top style='width:67.25pt;border:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt;text-align:center'><p class=MsoNormal><b>User</b></p></td>
            <td width=102 valign=top style='width:76.5pt;border:solid windowtext 1.0pt;border-left:none;padding:0in 5.4pt 0in 5.4pt;text-align:center'><p class=MsoNormal><b>Region</b></p></td>
            <td width=132 valign=top style='width:99.0pt;border:solid windowtext 1.0pt;border-left:none;padding:0in 5.4pt 0in 5.4pt;text-align:center'><p class=MsoNormal><b>Partner</b></p></td>
          </tr>
          <tr>
            <td width=90 valign=top style='width:67.25pt;border:solid windowtext 1.0pt;border-top:none;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>Bob</p></td>
            <td width=102 valign=top style='width:76.5pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>US</p></td>
            <td width=132 valign=top style='width:99.0pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>ABC</p></td>
          </tr>
          <tr>
            <td width=90 valign=top style='width:67.25pt;border:solid windowtext 1.0pt;border-top:none;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>Celestine</p></td>
            <td width=102 valign=top style='width:76.5pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>EMEA</p></td>
            <td width=132 valign=top style='width:99.0pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>ABC, XYZ</p></td>
          </tr>
        </table>
        <p class=MsoNormal>&nbsp;</p>

        <p class=MsoNormal>Row-filter policies from part 1:</p>

        <p class=MsoListParagraphCxSpFirst style='text-indent:-.25in'><span style='font-family:Symbol'>1. <span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span>Users in salesRegion.US role have access to rows where salesRegion = “US”</p>
        <p class=MsoListParagraphCxSpMiddle style='text-indent:-.25in'><span style='font-family:Symbol'>2. <span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span>Users in salesRegion.EMEA role have access to rows where salesRegion = “EMEA”</p>
        <p class=MsoListParagraphCxSpMiddle style='text-indent:-.25in'><span style='font-family:Symbol'>3. <span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span>Users in salesPartner.ABC role have access to rows where salesPartner = “ABC”</p>
        <p class=MsoListParagraphCxSpLast style='text-indent:-.25in'><span style='font-family:Symbol'>4. <span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span>Users in salesPartner.XYZ role has access to rows where salesPartner = “XYZ”</p>
        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal align=center style='text-align:center'>
          <img width=700 height=800 border=1 id="policy_table_ussales_rib" src="adventures_in_abac_2.files/fig1-policy_globalsalespartners_row_filter_sr_sp.jpg" alt="Fig 1. Apache Ranger&#8482; Table GlobalSalesPartners: row-filter policy to restrict access based on sales region and sales partner">
        </p>
        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal align=center style='text-align:center'>Fig 1. Apache Ranger&#8482; Table GlobalSalesPartners: row-filter policy to restrict access based on sales region and sales partner</p>
        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal>
          We noted previously that as the numbers of salesRegions and salesPartners rise, the number of
          roles and row filter conditions increases combinatorially, and rapidly becomes difficult to manage.
        </p>

        <p class=MsoNormal><span style='font-size:16.0pt;font-family:"Calibri Light",sans-serif;color:#2F5496'>&nbsp;</span></p>

        <h1>ABAC Principles</h1>
        <p class=MsoNormal>
          But what if Ranger policy engine had direct access to Bob‘s sales partners, and Bob‘s sales region, without
          reference to any roles he might be a member of? Then a row filter could be expressed this way, assuming Bob
          has access to data from only one sales region and sales partner
        </p>

        <p class=MsoNormal><span style='font-size:8.0pt;font-family:"Calibri Light",sans-serif;color:#2F5496'>&nbsp;</span></p>

        <p class=MsoListParagraphCxSpFirst style='text-indent:-.25in'><span style='font-family:Symbol'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span>&lt;partner attribute value in row&gt; == &lt;Bob’s partner&gt; AND &lt;sales region value in row&gt; == &lt;Bob’s region&gt;</p>

        <p class=MsoNormal><span style='font-size:16.0pt;font-family:"Calibri Light",sans-serif;color:#2F5496'>&nbsp;</span></p>

        <p class=MsoNormal>Now assume this can be generalized to work for all users:</p>

        <p class=MsoNormal><span style='font-size:8.0pt;font-family:"Calibri Light",sans-serif;color:#2F5496'>&nbsp;</span></p>

        <p class=MsoListParagraphCxSpFirst style='text-indent:-.25in'><span style='font-family:Symbol'><span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span>&lt;partner attribute value in row&gt; == $USER.partner AND &lt;sales region value in row&gt; == $USER.region</p>

        <h1>Welcome to Attribute Based Access Control (ABAC)!</h1>
        <p class=MsoNormal>
          In RBAC, the role to which a user is assigned membership is the central method of expressing what the user
          should be allowed access to. Bob is in the role partner.ABC, along with, say, Sarah and Thomas and Srikanth
          and Joon. Thus, all these users have access to partner ABC’s data.
        </p>
        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal>
          In ABAC, the central method of expressing what the user should be allowed to have access to is the value of
          the user’s attributes. Bob’s partner attribute value equals “ABC”, along with the partner attribute of Sarah
          and Thomas and Srikanth and Joon. Just as in the RBAC case, all these users have access to partner ABC’s data.
        </p>
        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal>
          But how do we program this in Apache Ranger? Apache Ranger uses a user-store, populated with users and their
          attributes typically loaded from LDAP, SCIM, Azure Active Directory (AAD), Okta, etc., by Apache Ranger
          usersync. If an attribute named partner is added to a user’s record on the identity provider, then that
          information will be gathered as part of the usersync and can be referenced within a Ranger policy condition
          as $USER.partner.
        </p>
        <p class=MsoNormal>&nbsp;</p>
        <h1>GlobalSalesPartners Row-Filters Using ABAC</h1>
        <p class=MsoNormal>
          Assume that the UserStore has been populated with salesRegion and salesPartner attributes for Bob and
          Celestine as follows:
        </p>
        <p class=MsoNormal>&nbsp;</p>

        <table class=MsoTableGrid style='width:225pt;margin-left:30.35pt;border-collapse:collapse;border:none'>
          <tr>
            <td style='width:75pt;border:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt;text-align:center'><p class=MsoNormal><b><span style='font-size:10.0pt'>User</span></b></p></td>
            <td style='width:75pt;border:solid windowtext 1.0pt;border-left:none;padding:0in 5.4pt 0in 5.4pt;text-align:center'><p class=MsoNormal><b><span style='font-size:10.0pt'>salesRegion</span></b></p></td>
            <td style='width:75pt;border:solid windowtext 1.0pt;border-left:none;padding:0in 5.4pt 0in 5.4pt;text-align:center'><p class=MsoNormal><b><span style='font-size:10.0pt'>salesPartner</span></b></p></td>
          </tr>
          <tr>
            <td style='width:75pt;border:solid windowtext 1.0pt;border-top:none;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>Bob</p></td>
            <td style='width:75pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>US</p></td>
            <td style='width:75pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>ABC</p></td>
          </tr>
          <tr>
            <td style='width:75pt;border:solid windowtext 1.0pt;border-top:none;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>Celestine</p></td>
            <td style='width:75pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>EMEA</p></td>
            <td style='width:75pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>XYZ</p></td>
          </tr>
        </table>

        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal>
          With ABAC, the 8 row filter conditions from the previous blog post become a single condition, matching the
          users’ partners and regions with the value in the salesPartner and salesRegion columns:
        </p>
        <p class=MsoNormal>&nbsp;</p>

        <p class=MsoNormal align=center style='text-align:center'>
          <img width=700 height=380 border=1 id="Picture 23" src="adventures_in_abac_2.files/fig2-policy_globalsalespartners_row_filter_abac.jpg" alt="Fig 2. Apache Ranger&#8482; Table GlobalSalesPartners: ABAC-based row-filter policy to restrict access based on sales region and sales partner">
        </p>

        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal align=center style='text-align:center'>Fig 2. Apache Ranger&#8482; Table GlobalSalesPartners: ABAC-based row-filter policy to restrict access based on sales region and sales partner</p>
        <p class=MsoNormal>&nbsp;</p>

        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal>
          This policy works for all users, not just those with salesRegion or salesPartner access like Bob’s or Celestine’s.
        </p>

        <h1>ABAC in Tag-Based Policies</h1>
        <p class=MsoNormal>
          Next, consider tables representing a single sales region, like USSales from blog post Part 1.
        </p>
        <p class=MsoNormal>&nbsp;</p>

        <table class=MsoTableGrid style='width:300pt;margin-left:30.35pt;border-collapse:collapse;border:none'>
          <tr>
            <td style='width:125pt;border:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt;text-align:center'><p class=MsoNormal><b><span style='font-size:10.0pt'>Resource</span></b></p></td>
            <td style='width:75pt;border:solid windowtext 1.0pt;border-left:none;padding:0in 5.4pt 0in 5.4pt;text-align:center'><p class=MsoNormal><b><span style='font-size:10.0pt'>Tag</span></b></p></td>
            <td style='width:100pt;border:solid windowtext 1.0pt;border-left:none;padding:0in 5.4pt 0in 5.4pt;text-align:center'><p class=MsoNormal><b><span style='font-size:10.0pt'>Tag Attribute</span></b></p></td>
          </tr>
          <tr>
            <td style='width:125pt;border:solid windowtext 1.0pt;border-top:none;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>Table: USSales</p></td>
            <td style='width:75pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>salesRegion</p></td>
            <td style='width:100pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt'><p class=MsoNormal>value=”US”</p></td>
          </tr>
        </table>

        <p class=MsoNormal>&nbsp;</p>

        <p class=MsoNormal>
          Allow only users in the salesRegion.US role to access resources tagged with salesRegion.value = ”US”.  Create
          a role-based (RBAC) tag policy that allows access to tagged tables based on the role membership of the user:
        </p>
        <p class=MsoNormal>&nbsp;</p>

        <p class=MsoNormal align=center style='text-align:center'>
          <img width=700 height=380 border=1 id="Picture 23" src="adventures_in_abac_2.files/fig3-policy_tag_based_on_user_role.jpg" alt="Fig 3. Apache Ranger&#8482; Tag-based policy allowing access to tagged tables based on the user’s role membership">
        </p>

        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal align=center style='text-align:center'>Fig 3. Apache Ranger&#8482; Tag-based policy allowing access to tagged tables based on the user’s role membership</p>
        <p class=MsoNormal>&nbsp;</p>

        <p class=MsoNormal>&nbsp;</p>

        <p class=MsoNormal>
          Using the RBAC method, we need to create a policy condition for each of the salesRegion.* roles.  Depending on
          how many salesRegions a company defines, this could get large.  And if they are continually being added or
          subtracted, the policy has to be commensurately updated.
        </p>

        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal>
          Let’s use ABAC to greatly simplify this process, by creating a tag policy that allows table access to any user
          whose salesRegion attribute matches the attribute of the salesRegion tag:
        </p>

        <p class=MsoNormal align=center style='text-align:center'>
          <img width=700 height=380 border=1 id="Picture 23" src="adventures_in_abac_2.files/fig4-policy_tag_policy_abac.jpg" alt="Fig 3. Apache Ranger&#8482; ABAC-based tag policy to allow access to tables based on the value of the user’s attribute.">
        </p>

        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal align=center style='text-align:center'>Fig 4. Apache Ranger&#8482; ABAC-based tag policy to allow access to tables based on the value of the user’s attribute.</p>
        <p class=MsoNormal>&nbsp;</p>

        <p class=MsoNormal>&nbsp;</p>
        <p class=MsoNormal>
          As we have seen, ABAC makes policy creation and maintenance much easier!  But what if the custodians of your
          Identity Provider are too busy to keep up with managing the additional attributes you need for ABAC?  Is there
          another way to populate the UserStore?  Yes! Check out Part 3 of this blog series to find out how you can
          retrieve UserStore entries from a variety of alternative sources!
        </p>

        <p class=MsoNormal>&nbsp;</p>
      </div>
    </div>
  </body>

  <footer>
    <div align=center >
      <a href="/blogs.html">Apache Ranger&#8482; blogs</a>
    </div>
  </footer>
</html>
